#include<bits/stdc++.h>
#include<cstdio>// snprintf
#include<cstring>
#include<unistd.h>
#include<cstdlib> // getenv
#include<sys/wait.h>
#include<sys/types.h>

using namespace std;

#define COMMAND_SIZE 1024
#define FORMAT "[%s@%s %s]#"

// shell定义  全局变量  
#define MAXARGC 128
char* g_argv[MAXARGC];
int g_argc = 0;

const char* GetUserName()// 库函数调用用户名
{
    const char* name = getenv("USER");
    return name == NULL ? "None" : name;
}

const char* GetHostName()//  库函数调用主机名字 
{
    const char* hostname = getenv("HOSTNAME");
    return hostname == NULL ? "None" : hostname;
}

const char* GetPwd()  //  库函数调用pwd 
{
    const char* pwd = getenv("PWD");
    return pwd == NULL ? "None" : pwd;
}

string DirName(const char* pwd)
{
#define SLASH "/"
    string dir = pwd;
    if(dir == SLASH) return false;
    auto pos = dir.rfind(SLASH);
    if(pos == string::npos) return "bug?";
    return dir.substr(pos + 1);
}

void MakeCommandLine(char cmd_prompt[], int size)//  写入命令行参数
{
    snprintf(cmd_prompt, size, FORMAT, GetUserName(), GetHostName(), DirName(GetPwd()).c_str());
    //snprintf(cmd_prompt, size, FORMAT, GetUserName(), GetHostName(), GetPwd());
}

void PrintCommandPrompt()  //  打印命令行
{
    char prompt[COMMAND_SIZE];
    MakeCommandLine(prompt, sizeof(prompt));
    printf("%s", prompt);
    fflush(stdout);
}

bool GetCommandline(char* out, int size)//  得到命令字符串
{
    char* c = fgets(out, size, stdin);
    if(c == NULL) return false;
    out[strlen(out) - 1] = 0;//  清理  \n
    if(strlen(out) == 0) return false;
    return true;
}

bool CommandParse(char* commandline)//  分割命令  
{
#define SEP " "
    g_argc = 0;
    g_argv[g_argc++] = strtok(commandline, SEP);
    while((bool)(g_argv[g_argc++] = strtok(nullptr, SEP)));
    g_argc--;
    return true;
}

void PrintArgv()//  打印argv函数   命令行参数表
{
    for(int i = 0; g_argv[i]; i++)
    {
        printf("argv[%d]->%s\n", i, g_argv[i]);
    }
    printf("argc: %d\n", g_argc);
}

int Execute()
{
    pid_t id = fork();
    if(id == 0)//  子进程  
    {
        execvp(g_argv[0], g_argv);
        exit(1);
    }

    pid_t rid = waitpid(id, nullptr, 0);
    (void) rid;
    
    return 0;
}

int main()
{
   while(1)
   {
        
        //输出命令行提示符  
        PrintCommandPrompt();
    
        //获取用户输入的命令
        char commandline[COMMAND_SIZE];
        if(!GetCommandline(commandline, sizeof(commandline)))
        continue;
    
        // 命令行分析  拆解  
        CommandParse(commandline);
        //PrintArgv();

        //  执行命令  通过创建子进程
        Execute();
   }
    return 0;
}
